﻿/*
 * Created by SharpDevelop.
 * User: Administrator
 * Date: 3/1/2011
 * Time: 8:30 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using TomatoSynchronizer.Entities;
using TomatoSynchronizer.Store;
using HtmlAgilityPack;

namespace TomatoSynchronizer.Synchronizer
{
	/// <summary>
	/// Description of ProductSynchronizer
	/// </summary>
	public static class ProductSynchronizer
	{
		public static void Synchronize(Site siteSrc,Site siteDest,HtmlWeb client,SyncDirection direction)
		{
			switch(direction)
			{
				case SyncDirection.Download:
					UpLoadItems(siteDest,siteSrc,client,direction);
					break;
				case SyncDirection.Upload:
					UpLoadItems(siteSrc,siteDest,client,direction);
					break;
				case SyncDirection.DownloadAndUpload:
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					break;
				case SyncDirection.UploadAndDownload:
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					break;
				case SyncDirection.Synchronize:										
					ProductStore productStoreDest = new ProductStore(siteDest,client);
					productStoreDest.Truncate();
					
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					break;
			}
		}
		
		private static void DownLoadItems(Site _siteSrc,Site _siteDest,HtmlWeb client,SyncDirection direction)
		{
			UpLoadItems(_siteDest,_siteSrc,client,direction);
		}
		
		private static void UpLoadItems(Site _siteSrc,Site _siteDest,HtmlWeb client,SyncDirection direction)
		{
			ProductStore productStoreSrc = new ProductStore(_siteSrc,client);
			ProductStore productStoreDest = new ProductStore(_siteDest,client);
			
			Product[] productsSrc =  productStoreSrc.LoadItems();
			Product[] productsDest =  productStoreDest.LoadItems();
			
			MappingStore mappingStoreSrc = new MappingStore(_siteSrc,_siteDest,"products");
			MappingStore mappingStoreDest = new MappingStore(_siteDest,_siteSrc,"products");
			
			foreach(Product ProductSrc in productsSrc)
			{
				//we assume the Product is not yet synchronized
				bool synchronized = false;
				
				//we check if a mapping already exists for this Product in the destination store
				foreach(Mapping mapping in mappingStoreSrc.Mappings)
				{
					if(mapping.SrcValue == ProductSrc.products_id)
					{
						//this Product already exists in the destination store
						//we check if everything changed since the last synchronization
						Product productDest = productStoreDest.LoadItem(mapping.DestValue);
						if(productDest != null)
						{
							synchronized = SynchronizeItem(ProductSrc,productDest,direction,mappingStoreSrc);
						}
						else
						{
							//the mapping exists, but the product has been deleted in the destination store
							//we set a flag that this mapping does not exists anymore
							mapping.Exists = false;
						}
					}
				}
				
				if(!synchronized)
				{
					//there is no mapping, we check if this Product already exists in the destination store
					foreach(Product ProductDest in productsDest)
					{
						if(ProductSrc.products_name == ProductDest.products_name)
						{
							Mapping mapping= new Mapping(ProductSrc.products_id,ProductDest.products_id,"products_id");
							mappingStoreSrc.Mappings.Add(mapping);
							
							synchronized = SynchronizeItem(ProductSrc,ProductDest,direction,mappingStoreSrc);
						}
					}
				}
				
				if(!synchronized)
				{
					//no mapping the Product is new
					//we insert it in the destination store
					string remoteId = string.Empty;
					
					remoteId = UploadItem(productStoreDest,ProductSrc,mappingStoreSrc);
					
					synchronized = remoteId != string.Empty;
					
					if(!synchronized)
					{
						throw new Exception("The Product " + ProductSrc.products_name + " has not been synchronized");
					}
					
					synchronized = true;
				}
				
				if(!synchronized)
				{
					throw new Exception("could not synchronize the Product " + ProductSrc.products_name);
				}
			}
			
			mappingStoreSrc.Save();
			
			//we save the mappings in the destination MappingStore too
			foreach(Mapping mapping in mappingStoreSrc.Mappings)
			{
				if(mapping.Exists)
				{
					Mapping mappingDest = new Mapping(mapping.DestValue,mapping.SrcValue,mapping.Property);
					mappingStoreDest.Mappings.Add(mappingDest);
				}
			}
			
			mappingStoreDest.Save();
			
			//we check if the 2 MappingStore are synchronized
			if(mappingStoreSrc.Mappings.Count != mappingStoreDest.Mappings.Count)
			{
//				throw new Exception("The mapping store are not synchronized");
			}
		}
		
		private static bool SynchronizeItem(Product ProductSrc,Product ProductDest,SyncDirection direction,MappingStore mappingStore)
		{
			bool synchronized = true;
			
			if(!ProductSrc.Equals(ProductDest))
			{
				synchronized = false;
				
				//we update the destination Product
				ProductSrc.products_id = ProductDest.products_id;
				
				synchronized = ProductDest.Store.UpdateItem(ProductSrc);
			}
			
			return synchronized;
		}
		
		private static string UploadItem(ProductStore productStoreDest,Product Product,MappingStore mappingStore)
		{
			string remoteId = string.Empty;
			
			remoteId = productStoreDest.InsertItem(Product);
			
			return remoteId;
		}		
	}
}
